package com.spzx.product.service.impl;


import com.alibaba.nacos.common.utils.StringUtils;
import com.spzx.product.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class TestServiceImpl implements TestService {

   @Autowired
   private StringRedisTemplate stringRedisTemplate;

   /**
    * 采用SpringDataRedis实现分布式锁
    * 原理：执行业务方法前先尝试获取锁（setnx存入key val），
    * 如果获取锁成功再执行业务代码，业务执行完毕后将锁释放(del key)
    */
   @Override
   public void testLock() throws InterruptedException {
      //0.先尝试获取锁 setnx key val
      String uuid = UUID.randomUUID().toString();
      //过期时间设置的长一点
      Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent("lock", uuid, 30, TimeUnit.MILLISECONDS);
      if(Boolean.TRUE.equals(flag)){
         //获取锁成功，执行业务代码
         //1.先从redis中通过key num获取值  key提前手动设置 num 初始值：0
         String value = stringRedisTemplate.opsForValue().get("num");

         Thread.sleep(20);

         //2.如果值为空则非法直接返回即可
         if (StringUtils.isBlank(value)) {
            return;
         }
         //3.对num值进行自增加一
         int num = Integer.parseInt(value);
         stringRedisTemplate.opsForValue().set("num", String.valueOf(++num));

         //4.将锁释放
         System.out.println("释放锁");
         String script = """
                 if redis.call('get', KEYS[1]) == ARGV[1]
                                         then return redis.call('del', KEYS[1])
                                     else
                                         return 0
                                     end
                 """;
         Boolean lock = stringRedisTemplate.execute(
                 new DefaultRedisScript<>(script, Boolean.class),
                 List.of("lock"),
                 uuid);
         System.out.println("result = " + lock);
//         if(uuid.equals(stringRedisTemplate.opsForValue().get("lock"))) {
//            Thread.sleep(20);
//            stringRedisTemplate.delete("lock");
//         }
      }else{
         //获取锁成功，执行业务代码
         Thread.sleep(10);
         System.out.println("重试");
         this.testLock();
      }
   }
}
    
//   @Override
//   public synchronized void testLock() {
//      // 查询Redis中的num值
//      String value = this.stringRedisTemplate.opsForValue().get("num");
//      // 没有该值return
//      if (StringUtils.isBlank(value)){
//         return ;
//      }
//      // 有值就转成int
//      int num = Integer.parseInt(value);
//      // 把Redis中的num值+1
//      this.stringRedisTemplate.opsForValue().set("num", String.valueOf(++num));
//   }
//}